local _handler = {}
_handler.__call = function(self, ...)
    if self.obj then
        self.func(self.obj, ...)
    else
        self.func(...)
    end
end
_handler.__eq = function(lhs, rhs)
    return lhs.func == rhs.func and lhs.obj == rhs.obj
end

function handlerEx(func, obj)
    return setmetatable({func = func, obj = obj}, _handler)
end

function handler(obj, method)
    return function(...)
        return method(obj, ...)
    end
end

function number_val(value,d_value)
	d_value=tonumber(d_value) or 0

	if value==nil or value==false or value=="" or  type(value)=="userdata" then return d_value end
	if value==true then return 1 end
	if type(value)=="string" then
		value=string.gsub(value, "^%s*(.-)%s*$", "%1")
		if value=="" then return d_value end
	end
	return tonumber(value) or d_value
end

function math.round(value)
    value = number_val(value)
    return math.floor(value + 0.5)
end

function tostringEx(value)
	if type(value) ~= "table" then
		return tostring(value);
	end

	local str;
	if table.isArray(value) then
		for k, v in ipairs(value) do
			if not str then
				str = tostring(v);
			else
				str = str .. "," .. tostring(v);
			end
		end
	else
		for k, v in pairs(value) do
			if not str then
				str = tostring(k) .. ":" .. tostring(v);
			else
				str = str .. "," .. tostring(k) .. ":" .. tostring(v);
			end
		end
	end
	return str and "{" .. str .. "}" or "{}";
end

function isInArray(t, val)
    for _, v in pairs(t) do
        if v == val then
            return true
        end
    end
    return false
end
function getInArrayKey(t, val)
    for key, v in pairs(t) do
        if v == val then
            return key
        end
    end
    return -1
end
function isInArrayKey(t, val)
    for key, v in pairs(t) do
        if key == val then
            return true
        end
    end
    return false
end
function copy_table(ori_tab)
    if (type(ori_tab) ~= "table") then
        return nil
    end
    local new_tab = {}
    for i,v in pairs(ori_tab) do
        local vtyp = type(v)
        if (vtyp == "table") then
            new_tab[i] = copy_table(v)
        elseif (vtyp == "thread") then
            new_tab[i] = v
        elseif (vtyp == "userdata") then
            new_tab[i] = v
        else
            new_tab[i] = v
        end
    end
    return new_tab
end

function gettablelen(t)
    local count=0
    for k,v in pairs(t) do
        count = count + 1
    end
    return count

end

function reverseTable(tab)
    local tmp = {}
    for i = 1, #tab do
        tmp[i] = table.remove(tab)
    end

    return tmp
end

function AddComponent(obj, luaClass, ...)
    local arg = {...}
    local luaObject = luaClass.new(unpack(arg))

    local luaBehaviour = obj.gameObject:AddComponent(typeof(LuaFramework.LuaBehaviour))
    luaBehaviour.LuaClassName = luaClass.__cname
    luaBehaviour:Init(luaObject)
    return luaObject
end

function GetLuaObject(obj)
    local luaBehaviours = obj:GetComponent(typeof(LuaFramework.LuaBehaviour))

    if luaBehaviours then
        return luaBehaviours.LuaObject
    end

    return nil
end

function GetComponent(obj, luaClassName)
    local luaBehaviours = obj:GetComponents(typeof(LuaFramework.LuaBehaviour))
    for i = 0, luaBehaviours.Length - 1 do
        local luaBehaviour = luaBehaviours[i]
        local luaObject = luaBehaviour.LuaObject
        if luaObject.__cname == luaClassName then
            return luaObject
        end

        if luaObject.__supers then
            for _, superClass in pairs(luaObject.__supers) do
                if superClass.__cname == luaClassName then
                    return luaObject
                end
            end
        end
    end
    return nil
end

function RemoveComponent(obj, luaClassName)
    local luaBehaviours = obj:GetComponents(typeof(LuaFramework.LuaBehaviour))
    for i = 0, luaBehaviours.Length - 1 do
        local luaBehaviour = luaBehaviours[i]
        local luaObject = luaBehaviour.LuaObject
        if luaObject.__cname == luaClassName then
            GameObject.Destroy(luaBehaviour)
            break
        end

        if luaObject.__supers then
            for _, superClass in pairs(luaObject.__supers)do
                if superClass.__cname == luaClassName then
                    GameObject.Destroy(luaBehaviour)
                    break
                end
            end
        end
    end
end

function GetBehaviour(obj, luaClassName)
    local luaBehaviours = obj:GetComponents(typeof(LuaFramework.LuaBehaviour))
    for i = 0, luaBehaviours.Length - 1 do
        local luaBehaviour = luaBehaviours[i]
        local luaObject = luaBehaviour.LuaObject
        if luaObject.__cname == luaClassName then
            return luaBehaviour
        end

        if luaObject.__supers then
            for _, superClass in pairs(luaObject.__supers) do
                if superClass.__cname == luaClassName then
                    return luaBehaviour
                end
            end
        end
    end
    return nil
end

function pairs(t)
    local rawNext = next
    local function next(t,k)
        local m = getmetatable(t)
        if m and m.__next then
            return m.__next(t, k)
        else
            return rawNext(t, k)
        end
    end
    return next, t, nil
end

function rawPairs(t)
    return next, t, nil
end